Core.ui = Core.ui || {};
/*
 Class for combining sets of input elements into single objects
 and providing a coherent API for interacting with them.
*/
Core.ui.FieldMapper = Class.extend({
	options : {
		fields : {},
		parent: null
	},
//
// constructor takes an object of options
	init : function (options) {
		this.data = {};
		this._fields = {};
		this.parentNode = null;
		this._defaultValues = {};

		this.options = options = jQuery.extend({}, this.options, options);
		if (this.options.parent) {
			this.parentNode = $(this.options.parent);
		}
		this._setFields(options.fields);
	},

	_setFields : function (fieldMap) {
		var field;
		for (var name in fieldMap){
			if (this.parentNode) {
				field = this.parentNode.find(fieldMap[name]);
			} else {
				field = $(fieldMap[name]);
			}
			this._fields[name] = field;
		}
		this.updateDefaults();
	},

	getFields: function() {
		return this._fields;
	},
	
	// Get a single field out of the mapper.
	// Will return all the fields if no arguments are given
	field: function (name) {
		if (name === undefined) {
			return this._fields;
		}
		if (this._fields[name] !== undefined) {
			return this._fields[name]
		}
	},

	// Read a single field.
	readField: function (name) {
		if (name in this._fields) {
			return this._fields[name].val();
		}
	},
/*
 Read the mapped fields. into name => value format.
*/
	read : function () {
		var name;
		for (name in this._fields) {
			var rawField = this._fields[name].get(0);
			var value = '';
			if (rawField && (rawField.type == 'radio' || rawField.type == 'checkbox')) {
				var otherRadios = $(rawField.form[rawField.name]);
				for (var i = 0, len = otherRadios.length; i < len; i++) {
					if (otherRadios[i].type != 'radio' && otherRadios[i].type != 'checkbox') {
						continue;
					}
					if (otherRadios[i].checked) {
						value = otherRadios[i].value;
						break;
					}
				}
			} else if (this._fields[name].length == 1) {
				value = this._fields[name].val();
			} else {
				value = [];
				this._fields[name].each(function (index, element) {
					value.push($(element).val());
				})
			}
			this.data[name] = (value === null || value === undefined) ? '' : value;
		}
		return $.extend({}, this.data);
	},
/*
 prepare data for post array. gets input[name] : value instead of fieldName : value
*/
	post : function () {
		this.read();
		var postData = {}, postName, name;
		for (name in this._fields) {
			postName = this._fields[name].attr('name');
			postData[postName] = this.data[name];
		}
		return postData;
	},
/*
 Set data to the fieldMapper takes a Object whose keys match the field names
 and sets the form input value for each one.
*/
	set: function (data) {
		var name, field, fieldName;
		for (name in data) {
			field = this._fields[name];
			if (!field) {
				continue;
			}
			if (field.get(0).type.match(/radio|checkbox/)) {
				var fieldData = jQuery.makeArray(data[name]);
				fieldName = field.attr('name');
				var otherInputs = $(field.get(0).form[fieldName]);
				for (var i = 0, len = otherInputs.length; i < len; i++) {
					if (this.parentNode && $(otherInputs[i]).parents(this.options.parent).length == 0) {
						continue;
					}
					if (jQuery.inArray(otherInputs[i].value, fieldData) > -1) {
						otherInputs[i].checked = true;
						break;
					}
				}
			} else {
				field.val(data[name]);
			}
		}
	},
/*
 Resets the data array
 clears validation errors and message
*/
	clear : function () {
		this.data = {};
		this._resetFields();
	},
/*
 Reset the field data, if the fields have a set 'value' attribute it will be retained
*/
	_resetFields: function () {
		var name, type, tag;
		for (name in this._fields) {
			var type = this._fields[name][0].type,
				tag = this._fields[name][0].tagName.toLowerCase();

			if (type == 'text' || type == 'password' || type == 'hidden' || tag == 'textarea') {
				this._fields[name][0].value = '';
			} else if (type == 'checkbox' || type == 'radio') {
				this._fields[name].attr('checked', false);
			} else if (tag == 'select') {
				this._fields[name].attr('selectedIndex', -1);
			}
		}
		this.set(this._defaultValues);
	},
	
/* 
 Update the default values, so if you saved, update these values; incase you reuse the widget again
*/	
	updateDefaults: function() {
		this._defaultValues = this.read();
	}
});